home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / mawk10.zip / FIELD.C < prev    next >
C/C++ Source or Header  |  1991-10-05  |  11KB  |  446 lines

  1.  
  2. /********************************************
  3. field.c
  4. copyright 1991, Michael D. Brennan
  5.  
  6. This is a source file for mawk, an implementation of
  7. the AWK programming language.
  8.  
  9. Mawk is distributed without warranty under the terms of
  10. the GNU General Public License, version 2, 1991.
  11. ********************************************/
  12.  
  13. /* $Log:    field.c,v $
  14.  * Revision 3.5.1.1  91/09/14  17:23:11  brennan
  15.  * VERSION 1.0
  16.  * 
  17.  * Revision 3.5  91/08/13  06:51:16  brennan
  18.  * VERSION .9994
  19.  * 
  20.  * Revision 3.4  91/07/17  15:11:39  brennan
  21.  * pass length of s to space_split
  22.  * 
  23.  * Revision 3.3  91/06/28  04:16:35  brennan
  24.  * VERSION 0.999
  25.  * 
  26.  * Revision 3.2  91/06/24  10:05:27  brennan
  27.  * FS="" and $0="", gave NF=1 should be 0
  28.  * 
  29.  * Revision 3.1  91/06/07  10:27:22  brennan
  30.  * VERSION 0.995
  31.  * 
  32.  * Revision 2.6  91/05/28  15:17:46  brennan
  33.  * removed STRING_BUFF back to temp_buff.string_buff
  34.  * 
  35.  * Revision 2.5  91/05/28  09:04:42  brennan
  36.  * removed main_buff
  37.  * 
  38.  * Revision 2.4  91/05/08  12:23:17  brennan
  39.  * RS = "" is now the same as RS = "\n\n+"
  40.  * 
  41.  * Revision 2.3  91/04/24  13:49:56  brennan
  42.  * eliminated unnecessary calculation of fields in field_assign()
  43.  * 
  44.  * Revision 2.2  91/04/09  12:39:00  brennan
  45.  * added static to funct decls to satisfy STARDENT compiler
  46.  * 
  47.  * Revision 2.1  91/04/08  08:23:01  brennan
  48.  * VERSION 0.97
  49.  * 
  50. */
  51.  
  52.  
  53. /* field.c */
  54.  
  55. #include "mawk.h"
  56. #include "field.h"
  57. #include "init.h"
  58. #include "memory.h"
  59. #include "scan.h"
  60. #include "bi_vars.h"
  61. #include "repl.h"
  62. #include "regexp.h"
  63.  
  64. union tbuff  temp_buff ;
  65. CELL  field[NUM_FIELDS] ;
  66.  
  67. /* statics */
  68. static void PROTO( build_field0, (void) ) ;
  69. static void PROTO( xcast, (CELL *) ) ;
  70. static void PROTO( set_rs_shadow, (void) ) ;
  71.  
  72. /* the order is important here, must be the same as
  73.    postion after field[MAX_FIELD] */
  74.  
  75. static char *biv_field_names[] = {
  76. "NF" , "RS" , "FS", "OFMT" } ;
  77.  
  78. /* a description of how to split based on RS.
  79.    If RS is changed, so is rs_shadow */
  80. SEPARATOR rs_shadow = {SEP_CHAR, '\n'} ;
  81. /* a splitting CELL version of FS */
  82. CELL fs_shadow = {C_SPACE} ;
  83. int   nf ;  
  84.   /* nf holds the true value of NF.  If nf < 0 , then
  85.      NF has not been computed, i.e., $0 has not been split
  86.   */
  87.  
  88. static void set_rs_shadow()
  89. { CELL c ;
  90.   STRING  *sval ;
  91.   char *s ;
  92.   unsigned len ;
  93.  
  94.   if ( rs_shadow.type == SEP_STR )  free_STRING((STRING*) rs_shadow.ptr) ;
  95.  
  96.   cast_for_split( cellcpy(&c, field+RS) ) ;
  97.   switch( c.type )
  98.   {
  99.     case C_RE :
  100.         if ( s = is_string_split(c.ptr, &len) )
  101.             if ( len == 1 )
  102.             { rs_shadow.type = SEP_CHAR ;
  103.               rs_shadow.c = s[0] ;
  104.             }
  105.             else
  106.             { rs_shadow.type = SEP_STR ;
  107.               rs_shadow.ptr = (PTR) new_STRING(s) ;
  108.             }
  109.         else
  110.         { rs_shadow.type = SEP_RE ;
  111.           rs_shadow.ptr = c.ptr ;
  112.         }
  113.         break ;
  114.  
  115.     case C_SPACE :
  116.         rs_shadow.type = SEP_CHAR ;
  117.         rs_shadow.c = ' ' ;
  118.         break ;
  119.  
  120.     case C_SNULL : /* RS becomes one or more blank lines */
  121.         rs_shadow.type = SEP_RE ;
  122.         sval = new_STRING( "\n\n+" ) ;
  123.         rs_shadow.ptr = re_compile(sval) ;
  124.         free_STRING(sval) ;
  125.         break ;
  126.  
  127.     default : bozo("bad cell in set_rs_shadow") ;
  128.   }
  129. }
  130.  
  131. void  field_init()
  132. { char **p = biv_field_names ;
  133.   SYMTAB *st_p ;
  134.   int i ;
  135.  
  136.   for(i = NF  ; i < NUM_FIELDS ; p++ , i++ )
  137.   {
  138.     st_p = insert( *p ) ;
  139.     st_p->type = ST_FIELD ;
  140.     st_p->stval.cp = &field[i] ;
  141.   }
  142.  
  143.   field[NF].type = C_DOUBLE ;
  144.   field[NF].dval = 0.0 ;
  145.   field[0].type = C_STRING ;
  146.   field[0].ptr = (PTR) & null_str ;
  147.   null_str.ref_cnt++ ;
  148.  
  149.   field[RS].type = C_STRING ;
  150.   field[RS].ptr =  (PTR) new_STRING( "\n" ) ;
  151.   /* rs_shadow already set */
  152.  
  153.   field[FS].type = C_STRING ;
  154.   field[FS].ptr = (PTR) new_STRING( " " ) ;
  155.   /* fs_shadow is already set */
  156.  
  157.   field[OFMT].type = C_STRING ;
  158.   field[OFMT].ptr = (PTR) new_STRING( "%.6g" ) ;
  159. }
  160.  
  161.  
  162.  
  163. void  set_field0( s, len)
  164.   char *s ;
  165.   unsigned len ;
  166.   cell_destroy( & field[0] ) ;
  167.   nf = -1 ;
  168.  
  169.   if ( len )
  170.   {
  171.     field[0].type = C_MBSTRN ;
  172.     field[0].ptr = (PTR) new_STRING( (char *) 0, len) ;
  173.     (void) memcpy( string(&field[0])->str, s, SIZE_T(len) ) ;
  174.   }
  175.   else
  176.   {
  177.     field[0].type = C_STRING ;
  178.     field[0].ptr = (PTR) &null_str ;
  179.     null_str.ref_cnt++ ;
  180.   }
  181. }
  182.  
  183.  
  184.  
  185. /* split field[0] into $1, $2 ... and set NF  */
  186.  
  187. void  split_field0()
  188. { register CELL *cp ;
  189.   register int i ;
  190.   CELL  c ;  /* copy field[0] here if not string */
  191.  
  192.  
  193.   if ( field[0].type < C_STRING )
  194.   { cast1_to_s(cellcpy(&c, field+0)) ;
  195.     cp = &c ;
  196.   }
  197.   else   cp = &field[0] ;
  198.  
  199.   if ( string(cp)->len == 0 )  nf = 0 ;
  200.   else
  201.   {
  202.     switch( fs_shadow.type )
  203.     {
  204.       case   C_SNULL :  /* FS == "" */
  205.       nf = 1 ;
  206.       cell_destroy(field+NF) ;
  207.       field[NF].type = C_DOUBLE ;
  208.       field[NF].dval = 1.0 ;
  209.       field[1].type = C_MBSTRN ;
  210.       field[1].ptr = cp->ptr ;
  211.  
  212.       if ( cp == field )  string(cp)->ref_cnt++ ;
  213.       /* else we gain one ref_cnt and lose one for a wash */
  214.  
  215.       return ;
  216.  
  217.       case  C_SPACE :
  218.       nf = space_split(string(cp)->str, string(cp)->len) ;
  219.       break ;
  220.  
  221.       default :
  222.       nf = re_split(string(cp)->str, fs_shadow.ptr) ;
  223.       break ;
  224.     }
  225.         
  226.     if ( nf > MAX_FIELD )
  227.         rt_overflow("maximum number of fields", MAX_FIELD) ;
  228.   }
  229.   
  230.   cell_destroy(field+NF) ;
  231.   field[NF].type = C_DOUBLE ;
  232.   field[NF].dval = (double) nf ;
  233.  
  234.   for( i = 1 ; i <= nf ; i++ )
  235.   {
  236.     cell_destroy(field+i) ;
  237.     field[i].ptr = temp_buff.ptr_buff[i-1] ;
  238.     field[i].type = C_MBSTRN ;
  239.   }
  240.  
  241.   if ( cp == &c )  free_STRING( string(cp) ) ;
  242. }
  243.  
  244. /*
  245.   assign CELL *cp to field[i]
  246.   and take care of all side effects
  247. */
  248.  
  249. void  field_assign( i, cp)
  250.   register int i ;
  251.   CELL *cp ;
  252. { register int j ;
  253.   CELL c ;
  254.  
  255.   /* update fields not up to date , unless we are
  256.      assigning to $0 */
  257.   if ( i != 0 && nf < 0 )  split_field0() ;
  258.  
  259.   switch( i )
  260.   {
  261.     case 0 :
  262.         cell_destroy(field) ;
  263.         nf = -1 ;
  264.         (void) cellcpy(field, cp) ;
  265.         break ; ;
  266.  
  267.     case  NF :
  268.         cell_destroy(field+NF) ;
  269.         (void) cellcpy(field+NF, cellcpy(&c,cp) ) ;
  270.         if ( c.type != C_DOUBLE )  cast1_to_d(&c) ;
  271.  
  272.         if ( (j = (int) c.dval) < 0 )
  273.             rt_error("negative value assigned to NF") ;
  274.         if ( j > MAX_FIELD )
  275.             rt_overflow("MAX_FIELD", MAX_FIELD) ;
  276.  
  277.         if ( j > nf )
  278.             for ( i = nf+1 ; i <= j ; i++ )
  279.             { cell_destroy(field+i) ;
  280.               field[i].type = C_STRING ;
  281.               field[i].ptr = (PTR) &null_str ;
  282.               null_str.ref_cnt++ ;
  283.             }
  284.  
  285.         nf = j ;
  286.         build_field0() ;
  287.         break ;
  288.  
  289.     case  RS :
  290.         cell_destroy(field+RS) ;
  291.         (void) cellcpy(field+RS, cp) ;
  292.         set_rs_shadow() ;
  293.         break ;
  294.  
  295.     case  FS :
  296.         cell_destroy(field+FS) ;
  297.         cast_for_split( cellcpy(&fs_shadow, cellcpy(field+FS, cp)) ) ;
  298.         break ;
  299.  
  300.     case OFMT : 
  301.         /* If the user does something stupid with OFMT, we could crash.
  302.            We'll make an attempt to protect ourselves here.  This is
  303.            why OFMT is made a field.
  304.  
  305.            The ptr of OFMT always has a valid STRING, even if assigned
  306.            a DOUBLE or NOINIT
  307.         */
  308.  
  309.         free_STRING( string(field+OFMT) ) ;
  310.         (void) cellcpy(field+OFMT, cp) ;
  311.         if ( field[OFMT].type < C_STRING ) /* !! */
  312.              field[OFMT].ptr = (PTR) new_STRING( "%.6g" ) ;
  313.         else
  314.         {
  315.           /* It's a string, but if it's really goofy it could still
  316.              damage us. Test it . */
  317.           temp_buff.string_buff[256] = 0 ;
  318.           (void) sprintf(temp_buff.string_buff, 
  319.              string(field+OFMT)->str, 3.1459) ;
  320.           if ( temp_buff.string_buff[256] )
  321.                 rt_error("OFMT assigned unusable value") ;
  322.         }
  323.         break ;
  324.            
  325.  
  326.     default:
  327.  
  328. #ifdef DEBUG 
  329.         if ( i < 0 )
  330.             bozo("negative field index in field_assign") ;
  331.         if ( i > MAX_FIELD )
  332.             bozo("large field index in field_assign") ;
  333. #endif
  334.  
  335.         cell_destroy(field+i) ;
  336.         (void) cellcpy(field+i, cp) ;
  337.         if ( i > nf )
  338.         { for ( j = nf+1 ; j < i ; j++ )
  339.           { cell_destroy(field+j) ;
  340.             field[j].type = C_STRING ;
  341.             field[j].ptr = (PTR) &null_str ;
  342.             null_str.ref_cnt++ ;
  343.           }
  344.           nf = i ;
  345.           cell_destroy(field+NF) ;
  346.           field[NF].type = C_DOUBLE ;
  347.           field[NF].dval = (double) i ;
  348.         }
  349.  
  350.         build_field0() ;
  351.  
  352.   }
  353. }
  354.  
  355.  
  356. /* get the string rep of a double without changing its
  357.    type */
  358.  
  359. static void  xcast( cp )
  360.   register CELL *cp ;
  361. {
  362.   switch ( cp->type )
  363.   {
  364.     case C_NOINIT :
  365.         cp->ptr = (PTR) &null_str ;
  366.         null_str.ref_cnt++ ;
  367.         break ;
  368.  
  369.     case C_DOUBLE :
  370.         (void) sprintf(temp_buff.string_buff, 
  371.           string(field+OFMT)->str, cp->dval) ;
  372.         cp->ptr = (PTR) new_STRING(temp_buff.string_buff) ;
  373.         break ;
  374.   }
  375. }
  376.  
  377.  
  378. /* construct field[0] from the other fields */
  379.  
  380. static void  build_field0()
  381.  
  382.  
  383. #ifdef DEBUG
  384.   if ( nf < 0 )  
  385.       bozo("nf <0 in build_field0") ;
  386. #endif
  387.  
  388.   cell_destroy( field+0 ) ;
  389.  
  390.   if ( nf == 0 )
  391.   { field[0].type = C_STRING ;
  392.     field[0].ptr = (PTR) &null_str ;
  393.     null_str.ref_cnt++ ;
  394.   }
  395.   else
  396.   if ( nf == 1 )  (void) cellcpy(field, field+1) ;
  397.  
  398.   else
  399.   { CELL  ofs ;
  400.     char *ofs_str ;
  401.     unsigned ofs_len , len0 = 0 ;
  402.     register int i ;
  403.     register char *p, *q ;
  404.  
  405.  
  406.     (void) cellcpy(& ofs , bi_vars + OFS) ;
  407.     if ( ofs.type < C_STRING )  cast1_to_s(&ofs) ;
  408.     ofs_str = string(&ofs)->str ;
  409.     ofs_len = string(&ofs)->len ;
  410.  
  411.  
  412.     for( i = 1 ; i <= nf ; i++ )
  413.     {
  414.       if ( field[i].type < C_STRING )  xcast(field+i) ;
  415.       len0 += string(field+i)->len + ofs_len ;
  416.     }
  417.     len0 -= ofs_len ;
  418.  
  419.     field[0].type = C_STRING ;
  420.     field[0].ptr = (PTR) new_STRING((char *) 0, len0) ;
  421.  
  422.     p = string(field)->str ;
  423.     for( i = 1 ; i < nf ; i++ )
  424.     {
  425.       (void) memcpy(p, string(field+i)->str, SIZE_T(string(field+i)->len)) ;
  426.       p += string(field+i)->len ;
  427.  
  428.       /* add the separator */
  429.       q = ofs_str ;
  430.       while ( *p++ = *q++ ) ;  p-- ;
  431.  
  432.       /* if not really string undo the xcast */
  433.       if ( field[i].type < C_STRING )
  434.               free_STRING( string(field+i) ) ;
  435.     }
  436.     /* do the last piece */
  437.     (void) memcpy(p, string(field+i)->str, SIZE_T(string(field+i)->len)) ;
  438.     if ( field[i].type < C_STRING )
  439.               free_STRING( string(field+i) ) ;
  440.     
  441.     free_STRING( string(&ofs) ) ;
  442.   } 
  443. }
  444.